home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 April: Mac OS SDK / Dev.CD Apr 96 SDK / Dev.CD Apr 96 SDK1.toast / Development Kits (Disc 1) / OpenDoc / Sample Code / Sample Editors⁄Viewers / Cappuccino / Source / CappuccinoDragDrop.cpp < prev    next >
Encoding:
Text File  |  1995-12-11  |  21.8 KB  |  798 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        CappuccinoDragDrop.cpp
  3.     
  4.     Contents:    Implements drag & drop support.
  5.     
  6.     Written by:    Troy Gaul
  7.     
  8.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. // -- Compiler/Preprocessor Switches --
  12.  
  13. #ifndef _COMPILERDEFS_
  14. #include "CompDefs.h"
  15. #endif
  16.  
  17. // -- OpenDoc Utilities --
  18.  
  19. #ifndef _EXCEPT_
  20. // Exceptions define several important macros (eg. CHECKENV)
  21. // which are used in the SOM method dispatch glue. If Except.h
  22. // is not included early enough, exceptions may not be thrown
  23. // correctly when returning from a SOM method with the "ev" parameter set.
  24. #include <Except.h>
  25. #endif
  26.  
  27. // -- Cappuccino Includes --
  28.  
  29. #ifndef _CAPPUCCINO_
  30. #include "Cappuccino.h"
  31. #endif
  32.  
  33. #ifndef _CAPPUCCINOACTION_
  34. #include "CappuccinoAction.h"
  35. #endif
  36.  
  37. #ifndef _CAPPUCCINOCONTENT_
  38. #include "CappuccinoContent.h"
  39. #endif
  40.  
  41. #ifndef _CAPPUCCINODEF_
  42. #include "CappuccinoDef.h"
  43. #endif
  44.  
  45. #ifndef _CAPPUCCINOGLOBALS_
  46. #include "CappuccinoGlobals.h"
  47. #endif
  48.  
  49. #ifndef _CAPPUCCINOPROMISE_
  50. #include "CappuccinoPromise.h"
  51. #endif
  52.  
  53. // -- OpenDoc Includes --
  54.  
  55. #ifndef SOM_ODDragItemIterator_xh
  56. #include <DgItmIt.xh>
  57. #endif
  58.  
  59. #ifndef SOM_ODDragAndDrop_xh
  60. #include <DragDrp.xh>
  61. #endif
  62.  
  63. #ifndef SOM_ODFacet_xh
  64. #include <Facet.xh>
  65. #endif
  66.  
  67. #ifndef SOM_ODFrame_xh
  68. #include <Frame.xh>
  69. #endif
  70.  
  71. #ifndef _ODDEBUG_
  72. #include <ODDebug.h>
  73. #endif
  74.  
  75. #ifndef _ODTYPES_
  76. #include <ODTypes.h>
  77. #endif
  78.  
  79. #ifndef SOM_ODSession_xh
  80. #include <ODSessn.xh>
  81. #endif
  82.  
  83. #ifndef SOM_ODShape_xh
  84. #include <Shape.xh>
  85. #endif
  86.  
  87. #ifndef SOM_Module_OpenDoc_StdProps_defined
  88. #include <StdProps.xh>
  89. #endif
  90.  
  91. #ifndef SOM_Module_OpenDoc_StdTypes_defined
  92. #include <StdTypes.xh>
  93. #endif
  94.  
  95. #ifndef SOM_ODStorageUnit_xh
  96. #include <StorageU.xh>
  97. #endif
  98.  
  99. #ifndef SOM_ODTranslation_xh
  100. #include <Translt.xh>
  101. #endif
  102.  
  103. #ifndef SOM_ODUndo_xh
  104. #include <Undo.xh>
  105. #endif
  106.  
  107. // -- OpenDoc Utilities --
  108.  
  109. #ifndef _BARRAY_
  110. #include <BArray.h>
  111. #endif
  112.  
  113. #ifndef _FOCUSLIB_
  114. #include <FocusLib.h>
  115. #endif
  116.  
  117. #ifndef _ODUTILS_
  118. #include <ODUtils.h>
  119. #endif
  120.  
  121. #ifndef _STDTYPIO_
  122. #include <StdTypIO.h>
  123. #endif
  124.  
  125. #ifndef _STORUTIL_
  126. #include <StorUtil.h>
  127. #endif
  128.  
  129. #ifndef _TEMPOBJ_
  130. #include <TempObj.h>
  131. #endif
  132.  
  133. //==============================================================================
  134. #pragma mark    • ODPart overrides •
  135. //==============================================================================
  136.  
  137. //------------------------------------------------------------------------------
  138. // Method:        FulfillPromise
  139. // Origin:        ODPart
  140. //
  141. // Description:    This method is called when a promise we have given for a
  142. //                storage unit needs to be fulfilled with the actual data.
  143. //------------------------------------------------------------------------------
  144.  
  145. void Cappuccino::FulfillPromise( Environment*            ev,
  146.                                  ODStorageUnitView*        promiseSUView )
  147. {
  148.     SOM_Trace("Cappuccino","FulfillPromise");
  149.     
  150.     CPromise* promise = CPromise::GetPromiseFromSUView(ev, promiseSUView);
  151.     THROW_IF_NULL(promise);
  152.     
  153.     promise->Fulfill(ev, promiseSUView);
  154. }
  155.  
  156. //------------------------------------------------------------------------------
  157. // Method:        DropCompleted
  158. // Origin:        ODPart
  159. //
  160. // Description:    This method is called when an asynchronous drag, initiated by
  161. //                this part, has completed.
  162. //
  163. // Note:        OpenDoc version 1.0 for the Macintosh does not support
  164. //                asynchronous dragging, so this routine will never be called.
  165. //                It is included here so it can be filled in in case it is 
  166. //                supported in the future.
  167. //------------------------------------------------------------------------------
  168.  
  169. void Cappuccino::DropCompleted( Environment*        ev,
  170.                                 ODPart*             destPart,
  171.                                 ODDropResult        dropResult )
  172. {
  173.     SOM_Trace("Cappuccino","DropCompleted");
  174. }
  175.  
  176. //------------------------------------------------------------------------------
  177. // Method:        DragEnter
  178. // Origin:        ODPart
  179. //
  180. // Description:    This method is called when a drag enters a facet that belongs
  181. //                to this part.  We should check to see if we can accept the
  182. //                drag and highlight the facet if so.
  183. //------------------------------------------------------------------------------
  184.  
  185. ODDragResult Cappuccino::DragEnter( Environment*            ev,
  186.                                     ODDragItemIterator*        dragInfo,
  187.                                     ODFacet*                facet,
  188.                                     ODPoint*                where )
  189. {
  190.     SOM_Trace("Cappuccino","DragEnter");
  191.     
  192. #ifndef qViewerBuild
  193.     ODDragResult acceptable = this->IsDragSupported(ev, dragInfo, facet);
  194.  
  195.     if ( acceptable )
  196.     {
  197.         // We can accept everything, so highlight the facet.
  198.  
  199.         ODDragAndDrop* dad = fSession->GetDragAndDrop(ev);
  200.         ODULong dragAttributes = dad->GetDragAttributes(ev);
  201.         
  202.         if (!(dragAttributes & kODDragIsInSourceFrame))
  203.         {
  204.             this->HighlightFacet(ev, facet, kODTrue);
  205.         }
  206.     }
  207.     
  208.     return acceptable;
  209. #else
  210.     return kODFalse;
  211. #endif
  212. }
  213.  
  214. //------------------------------------------------------------------------------
  215. // Method:        DragWithin
  216. // Origin:        ODPart
  217. //
  218. // Description:    This method is called while a drag is still within a facet
  219. //                belonging to this part.  Since we already highlighted it during
  220. //                DragEnter, we don't need to do anything here.  If we had
  221. //                multiple drag areas, we could track them in this routine.
  222. //------------------------------------------------------------------------------
  223.  
  224. ODDragResult Cappuccino::DragWithin( Environment*            ev,
  225.                                      ODDragItemIterator*    dragInfo,
  226.                                      ODFacet*                facet,
  227.                                      ODPoint*                where )
  228. {
  229.     SOM_Trace("Cappuccino","DragWithin");
  230.  
  231. #ifndef qViewerBuild
  232.     return kODTrue;
  233. #else
  234.     return kODFalse;
  235. #endif
  236. }
  237.  
  238. //------------------------------------------------------------------------------
  239. // Method:        DragLeave
  240. // Origin:        ODPart
  241. //
  242. // Description:    This method is called when a drag leaves a facet belonging to
  243. //                this part after it had previously entered it.  We must remove
  244. //                our drag highlighting at this point.
  245. //------------------------------------------------------------------------------
  246.  
  247. void Cappuccino::DragLeave( Environment*            ev,
  248.                             ODFacet*                facet,
  249.                             ODPoint*                where)
  250. {
  251.     SOM_Trace("Cappuccino","DragLeave");
  252.  
  253. #ifndef qViewerBuild
  254.     this->HighlightFacet(ev, facet, kODFalse);
  255. #endif
  256. }
  257.  
  258. //------------------------------------------------------------------------------
  259. // Method:        Drop
  260. // Origin:        ODPart
  261. //
  262. // Description:    This method is called when a drag has resulted in dropping
  263. //                the content onto a facet belonging to this part.  We must
  264. //                remove the drag highlighting and handle the drop here.
  265. //------------------------------------------------------------------------------
  266.  
  267. ODDropResult Cappuccino::Drop( Environment*                ev,
  268.                                ODDragItemIterator*        dropInfo,
  269.                                ODFacet*                    facet,
  270.                                ODPoint*                    where )
  271. {
  272.     SOM_Trace("Cappuccino","Drop");
  273.     
  274. #ifndef qViewerBuild
  275.     ODDropResult result = kODDropFail;
  276.     
  277.     // Remove the drag highlighting.
  278.     this->HighlightFacet(ev, facet, kODFalse);
  279.     
  280.     ODULong dragAttributes = fSession->GetDragAndDrop(ev)->GetDragAttributes(ev);
  281.  
  282.     if ( dragAttributes & kODDropIsInSourcePart )
  283.     {
  284.         result = kODDropFail;
  285.     }
  286.     else if ( this->IsDragSupported(ev, dropInfo, facet) )
  287.     {
  288.         if ( !this->TryToEdit(ev, facet->GetFrame(ev)) )
  289.             return kODDropFail;
  290.  
  291.         // Inspect the type of data being dragged to see if we can accept it.
  292.         for ( ODStorageUnit* dropSU = dropInfo->First(ev) ; dropSU ; 
  293.               dropSU = dropInfo->Next(ev) )
  294.         {
  295.             if ( CCappuccinoContent::HasValidContent(ev, dropSU) )
  296.             {
  297.                 result = (dragAttributes & kODDropIsMove) ? kODDropMove 
  298.                                                           : kODDropCopy;
  299.                 
  300.                 // Determine the nature of the drag (copy vs. move).
  301.                 if ( dragAttributes & kODDropIsPasteAs ) 
  302.                 {
  303.                     ODBoolean pasteLink;
  304.                     this->DoDropPasteAs(ev, facet, &pasteLink);
  305.                     
  306.                     // We don't currently support linking, but we'll check
  307.                     // this flag and set the result appropriately so that
  308.                     // when support is added, we're handling it correctly.
  309.                     if ( pasteLink )
  310.                     {
  311.                         // If we're pasting a link, we have to make sure it's
  312.                         // a copy.  A move is not possible, because it would
  313.                         // mean that we'd be removing the source of the link.
  314.                         result = kODDropCopy;
  315.                     }
  316.                 }
  317.                 else
  318.                 {
  319.                     CCappuccinoContent* content = new CCappuccinoContent(this);
  320.                     TempRefCounted contentTemp = content;
  321.                     content->InitCappuccinoContent(ev, dropSU);
  322.     
  323.                     CDropAction* action = new CDropAction(this, content);
  324.                     action->Perform(ev);
  325.                 }
  326.             }
  327.         }
  328.     }
  329.     
  330.     return result;
  331. #else
  332.     return kODDropFail;
  333. #endif
  334. }
  335.  
  336. //==============================================================================
  337. #pragma mark    • Cappuccino functions •
  338. //==============================================================================
  339.  
  340. //------------------------------------------------------------------------------
  341. // Method:        HighlightFacet
  342. // Origin:        Cappuccino
  343. //
  344. // Description:    This method is called when a facet of this part needs to be
  345. //                highlighted because it is able to accept a drop.
  346. //------------------------------------------------------------------------------
  347.  
  348. void Cappuccino::HighlightFacet( Environment*        ev,
  349.                                  ODFacet*            facet, 
  350.                                  ODBoolean            show)
  351. {
  352. #ifndef qViewerBuild
  353.     ODDragAndDrop* dad = fSession->GetDragAndDrop(ev);
  354.     
  355.     CFocus forDrawing(ev, facet);
  356.     
  357.     if ( show )
  358.     {
  359.         ODFrame*    displayFrame = facet->GetFrame(ev);
  360.         TempODShape    frameShape     = displayFrame->AcquireFrameShape(ev, kODNULL);
  361.         RgnHandle    bRgn         = frameShape->GetQDRegion(ev);
  362.         
  363.         ShowDragHilite(dad->GetDragReference(ev), bRgn, true);
  364.         
  365.         fHighlightedDragFacet = facet;
  366.     }
  367.     else 
  368.     {
  369.         if ( fHighlightedDragFacet != kODNULL )
  370.         {
  371.             HideDragHilite(dad->GetDragReference(ev));
  372.             fHighlightedDragFacet = kODNULL;
  373.         }
  374.     }
  375. #endif
  376. }
  377.  
  378. //------------------------------------------------------------------------------
  379. // Method:        IsDragSupported
  380. // Origin:        Cappuccino
  381. //
  382. // Description:    This method is called when the part needs to know if the
  383. //                contents of a particular kind of drag are supported.
  384. //                
  385. // Notes:        For a drag to be supported, the contents of all of the drag
  386. //                items must be supported.
  387. //
  388. //                In addition, Cappuccino only supports one piece of content, and
  389. //                thus can only accept a drag of one item (two or more items will
  390. //                always be rejected, regardless of content).
  391. //------------------------------------------------------------------------------
  392.  
  393. ODBoolean Cappuccino::IsDragSupported( Environment*            ev,
  394.                                        ODDragItemIterator*    dragInfo,
  395.                                        ODFacet*                facet )
  396. {
  397.     SOM_Trace("Cappuccino","DragEnter");
  398.     
  399. #ifndef qViewerBuild
  400.     ODBoolean isSupported = kODFalse;
  401.     
  402.     if ( !fReadOnlyStorage && 
  403.          (facet->GetFrame(ev)->GetLinkStatus(ev) != kODInLinkDestination) )
  404.     {
  405.         isSupported = kODTrue;
  406.         ODULong count = 0;
  407.  
  408.         // Inspect the type of data being dragged to see if we can accept it.
  409.         for ( ODStorageUnit* dragSU = dragInfo->First(ev) ; dragSU ; 
  410.               dragSU = dragInfo->Next(ev) )
  411.         {
  412.             // The recipe says that in order to accept a drag, we have to be
  413.             // able to accept ALL of the contents of the drag.  Since we only
  414.             // have one string, the most that we can handle is one item.
  415.             if ( ++count > 1 )
  416.             {
  417.                 isSupported = kODFalse;
  418.                 break;
  419.             }
  420.             
  421.             // Determine if we support the drag content and if it would
  422.             // need to be translated.
  423.             ODBoolean itemHasValidData = CCappuccinoContent::HasValidContent(ev, dragSU);
  424.             
  425.             // We have to be able to accept everything dropped on us, so see
  426.             // if this item is acceptable, and if not, reject the entire drag.
  427.             if ( !itemHasValidData )
  428.             {
  429.                 isSupported = kODFalse;
  430.                 break;
  431.             }
  432.         }
  433.         
  434.     }
  435.     
  436.     return isSupported;
  437. #else
  438.     return kODFalse;
  439. #endif
  440. }
  441.  
  442. //------------------------------------------------------------------------------
  443. // Method:        InitiateDrag
  444. // Origin:        Cappuccino
  445. //
  446. // Description:    This method is called when the user clicks the mouse in the
  447. //                part and starts dragging, causing it to need to start dragging
  448. //                its content around.  
  449. //
  450. //                This method puts promises to the part's content into the drag
  451. //                and drop storage unit, calls OpenDoc to perform the drag, and
  452. //                then handles the result of the drag.
  453. //------------------------------------------------------------------------------
  454.  
  455. ODDropResult Cappuccino::InitiateDrag( Environment*        ev,
  456.                                        ODEventData*        event, 
  457.                                        ODFacet*            facet, 
  458.                                        ODPoint&            where)
  459. {
  460.     SOM_Trace("Cappuccino","InitateDrag");
  461.     
  462.     ODBoolean canChange = !fReadOnlyStorage && 
  463.                 (facet->GetFrame(ev)->GetLinkStatus(ev) != kODInLinkDestination);
  464.  
  465.     ODDropResult dropResult = kODDropFail;
  466.     
  467.     // Get the ODDragAndDrop object from the session.
  468.     ODDragAndDrop* dragAndDrop = fSession->GetDragAndDrop(ev);
  469.     
  470.     // Reinitialize the ODDragAndDrop object.
  471.     dragAndDrop->Clear(ev);
  472.     
  473.     // Get the Storage Unit where data for dragged objects are going to be written.
  474.     ODStorageUnit* su = dragAndDrop->GetContentStorageUnit(ev);
  475.     
  476.     // Write out the data.
  477.     this->CloneContents(ev, su, canChange ? kODCloneCut : kODCloneCopy, 
  478.                         facet->GetFrame(ev), kIsNotForClipboard);
  479.     
  480.     // Write out the mouse down offset.
  481.     ODSetPointProp(ev, su, kODPropMouseDownOffset, kODPoint, &where);
  482.     
  483.     // Initiate the drag.
  484.     TempODPart destPart = kODNULL;
  485.     
  486.     // Add a begin token to the undo stack to wrap any undo actions that are
  487.     // added in the course of the drag (since the drag should be perceived by
  488.     // the user as a single operation).
  489.     CDragBeginAction* beginAction = new CDragBeginAction(this);
  490.     beginAction->Perform(ev);
  491.         
  492.     TRY
  493.         // Get the drag region.
  494.         ODRgnHandle dragRgn = this->CreateDragRegion(ev, facet);
  495.         
  496.         TRY
  497.             // Create byte arrays for dragRn and refCon (which is the event record).
  498.             TempODByteArray dragRgnBA = CreateByteArray(&dragRgn, sizeof(RgnHandle));
  499.             TempODByteArray eventBA   = CreateByteArray(&event, sizeof(ODEventData*));    // event is of type ODEventData*.
  500.             
  501.             // Here we have an ODPart that is used in order to store the
  502.             // result of the drag (its destination).  We can't use destPart
  503.             // for this purpose because it is a TempRef, and we need to be
  504.             // able to take the address of the ODPart pointer to pass into
  505.             // StartDrag.
  506.             ODPart* theDestPart = kODNULL;
  507.             
  508.             dropResult = dragAndDrop->StartDrag(ev, facet->GetFrame(ev), 
  509.                                                 kODDragImageRegionHandle, 
  510.                                                 dragRgnBA, &theDestPart, eventBA);
  511.             
  512.             // Assign the resulting part to our temp object so that it
  513.             // will be released automatically when it goes out of scope.
  514.             destPart = theDestPart;
  515.         CATCH_ALL
  516.             DisposeRgn(dragRgn);
  517.             RERAISE;
  518.         ENDTRY
  519.         
  520.         DisposeRgn(dragRgn);
  521.         
  522.         // Handle the result of the drag.
  523.         if ( dropResult == kODDropCopy || dropResult == kODDropMove )
  524.         {
  525.             if ( ODObjectsAreEqual(ev, destPart, fSelf) )
  526.             {
  527.                 // Dragged back into ourself, ignore.
  528.             }
  529.             else if ( dropResult == kODDropMove )
  530.             {
  531. #ifndef qViewerBuild
  532.                 // It was a move, so we need to remove it from our content.
  533.                 if ( canChange )
  534.                     this->DoClear(ev, facet->GetFrame(ev));
  535. #endif
  536.             }
  537.         }
  538.     CATCH_ALL
  539.         fSession->GetUndo(ev)->AbortCurrentTransaction(ev);
  540.         gGlobals->fDragPromises->Clear(ev);
  541.         RERAISE;
  542.     ENDTRY
  543.     
  544.     gGlobals->fDragPromises->Clear(ev);
  545.  
  546.     // Finish off the undo action.
  547.     if ( dropResult == kODDropFail )
  548.     {
  549.         fSession->GetUndo(ev)->AbortCurrentTransaction(ev);
  550.     }
  551.     else
  552.     {
  553.         // Add an end token to the undo stack to wrap any undo actions that are
  554.         // added in the course of the drag.
  555.         CDragEndAction* endAction = new CDragEndAction(this);
  556.         endAction->Perform(ev);
  557.     }
  558.     
  559.     return dropResult;
  560. }
  561.  
  562. //------------------------------------------------------------------------------
  563. // Method:        CreateDragRegion
  564. // Origin:        Cappuccino
  565. //
  566. // Description:    This method is called when we need to create a region handle
  567. //                that represents the area to be dragged for a drag and drop.
  568. //------------------------------------------------------------------------------
  569.  
  570. ODRgnHandle Cappuccino::CreateDragRegion( Environment*        ev,
  571.                                           ODFacet*            facet )
  572. {
  573.     ASSERT_NOT_NULL(facet);
  574.  
  575.     ODRgnHandle dragRgn = ODNewRgn();
  576.  
  577.     TRY
  578.         ODFrame* frame = facet->GetFrame(ev);
  579.         TempODShape frameShape = kODNULL;
  580.         
  581.         if ( frame->IsRoot(ev) )
  582.         {
  583.             // If we're at the root, we need to use the bounds of our shape so
  584.             // that the cutout corner (for the grow box) isn't included in the
  585.             // shape.
  586.             frameShape = ODCopyAndRelease(ev, frame->AcquireFrameShape(ev, kODNULL));
  587.             
  588.             ODRect bounds;
  589.             frameShape->GetBoundingBox(ev, &bounds);
  590.             frameShape->SetRectangle(ev, &bounds);
  591.         }
  592.         else
  593.         {
  594.             frameShape = frame->AcquireFrameShape(ev, kODNULL);
  595.         }
  596.         
  597.         // Get the region from the shape.
  598.         CopyRgn(frameShape->GetQDRegion(ev), dragRgn);
  599.     
  600.         // Inset the region and subtract it from the original.  This is
  601.         // done to get a region that just contains the frame of the area
  602.         // and isn't filled in.
  603.         {
  604.             ODRgnHandle insetRgn = ODNewRgn();
  605.             
  606.             CopyRgn(dragRgn, insetRgn);
  607.             InsetRgn(insetRgn, 1, 1);
  608.             DiffRgn(dragRgn, insetRgn, dragRgn);
  609.     
  610.             ODDisposeHandle((ODHandle) insetRgn);
  611.         }
  612.         
  613.         // Put the region in global coordinates.
  614.         {
  615.             CFocus forMapping(ev, facet);
  616.             
  617.             Point localToGlobalTrans = { 0, 0 };
  618.             LocalToGlobal(&localToGlobalTrans);
  619.             OffsetRgn(dragRgn, localToGlobalTrans.h, localToGlobalTrans.v);
  620.         }
  621.     CATCH_ALL
  622.         ODDisposeHandle((ODHandle) dragRgn);
  623.         RERAISE;
  624.     ENDTRY
  625.         
  626.     return dragRgn;
  627. }
  628.  
  629. //------------------------------------------------------------------------------
  630. // Method:        DoDropPasteAs
  631. // Origin:        Cappuccino
  632. //
  633. // Description:    This method is called by the part when the user uses the 
  634. //                approprate drag-and-drop modifier keys.
  635. //------------------------------------------------------------------------------
  636.  
  637. void Cappuccino::DoDropPasteAs( Environment*            ev,
  638.                                 ODFacet*                facet,
  639.                                 ODBoolean*                pasteLink )
  640. {
  641.     SOM_Trace("Cappuccino","DoPaste");
  642.     
  643. #ifndef qViewerBuild
  644.     ASSERT_NOT_NULL(facet);
  645.  
  646.     ODDragAndDrop* dad = fSession->GetDragAndDrop(ev);    
  647.     ODStorageUnit* contentSU = dad->GetContentStorageUnit(ev);
  648.     
  649.     ODPasteAsResult pasteAsResult;
  650.     pasteAsResult.selectedKind    = kODNULL;
  651.     pasteAsResult.translateKind    = kODNULL;
  652.     pasteAsResult.editor        = kODNULL;
  653.     TempODPasteAsResult    pasteAsResultTemp = &pasteAsResult;    
  654.         
  655.     // Parameters except pasteAsResult are omitted
  656.     if ( dad->ShowPasteAsDialog(ev,
  657.                                 kODTrue,                // canPasteLink
  658.                                 kODPasteAsMergeOnly,     // mergeSetting
  659.                                 facet,
  660.                                 kODNullTypeToken,        // viewtype
  661.                                 contentSU,
  662.                                 &pasteAsResult) )
  663.     {
  664.         this->HandlePasteAsResult(ev, pasteAsResult, contentSU);
  665.     }
  666.     
  667.     // If we're pasting it as a link, inform the caller.
  668.     *pasteLink = pasteAsResult.pasteLinkSetting;
  669.     
  670. #endif
  671. }
  672.  
  673. //==============================================================================
  674. #pragma mark    • Data Interchange •
  675. //==============================================================================
  676.  
  677. //------------------------------------------------------------------------------
  678. // Method:        AnnotateInterchangeSU
  679. // Origin:        Cappuccino
  680. //
  681. // Description:    This method is called by the part when it is putting data onto
  682. //                the clipboard or drag-and-drop storage unit.  It adds an
  683. //                annotation that indicates the suggested frame shape based on
  684. //                the current frame shape.
  685. //------------------------------------------------------------------------------
  686.  
  687. void Cappuccino::AnnotateInterchangeSU( Environment*    ev,
  688.                                         ODStorageUnit*    su,
  689.                                         ODFrame*        frame )
  690. {
  691.     SOM_Trace("Cappuccino","AnnotateInterchangeSU");
  692.  
  693.     ODSUForceFocus(ev, su, kODPropSuggestedFrameShape, kODNULL);
  694.     
  695.     TempODShape frameShape = kODNULL;
  696.     
  697.     if ( frame->IsRoot(ev) )
  698.     {
  699.         // If we're at the root, we need to use the bounds of our shape so
  700.         // that the cutout corner (for the grow box) isn't included in the
  701.         // shape that we write out.
  702.         frameShape = ODCopyAndRelease(ev, frame->AcquireFrameShape(ev, kODNULL));
  703.         
  704.         ODRect bounds;
  705.         frameShape->GetBoundingBox(ev, &bounds);
  706.         frameShape->SetRectangle(ev, &bounds);
  707.     }
  708.     else
  709.     {
  710.         frameShape = frame->AcquireFrameShape(ev, kODNULL);
  711.     }
  712.     frameShape->WriteShape(ev, su);
  713. }
  714.  
  715. //------------------------------------------------------------------------------
  716. // Method:        CloneContents
  717. // Origin:        Cappuccino
  718. //
  719. // Description:    This method is called by the part when the user chooses the
  720. //                Copy/Cut menu item or starts a drag.  It promises the part's
  721. //                content to the given storage unit.
  722. //------------------------------------------------------------------------------
  723.  
  724. void Cappuccino::CloneContents( Environment*        ev,
  725.                                  ODStorageUnit*        su,
  726.                                 ODCloneKind            cloneKind,
  727.                                 ODFrame*            scopeFrame,
  728.                                 ODBoolean            isForClipboard )
  729. {
  730.     SOM_Trace("Cappuccino","CloneContents");
  731.  
  732.     ODDraft*    fromDraft = ODGetDraft(ev, fSelf);
  733.     ODDraft*    toDraft   = su->GetDraft(ev);
  734.     ODDraftKey    key          = kODNULLKey;
  735.     
  736.     ODVolatile(key);
  737.     
  738.     TRY
  739.         key = fromDraft->BeginClone(ev, toDraft, kODNULL, cloneKind);
  740.         
  741.         // Verify that the properties we want to write into exist.
  742.         this->CheckAndAddProperties(ev, su);
  743.             
  744.         // Write out the part's content annotation.
  745.         this->ExternalizeStateInfo(ev, su, key, scopeFrame);
  746.  
  747.         WASSERT(fContent != kODNULL);
  748.         
  749.         fContent->Promise(ev, su, key, isForClipboard, this);
  750.  
  751.         fromDraft->EndClone(ev, key);
  752.     CATCH_ALL
  753.         if ( key != kODNULLKey )
  754.             fromDraft->AbortClone(ev, key);
  755.         RERAISE;
  756.     ENDTRY
  757.     
  758.     this->AnnotateInterchangeSU(ev, su, scopeFrame);
  759. }
  760.  
  761. //------------------------------------------------------------------------------
  762. // Method:        HandlePasteAsResult
  763. // Origin:        Cappuccino
  764. //
  765. // Description:    This method is called by the part when the the Paste As dialog
  766. //                (from either the Paste As command or from a drag-and-drop has 
  767. //                been dismissed by clicking on the OK button.
  768. //------------------------------------------------------------------------------
  769.  
  770. void Cappuccino::HandlePasteAsResult( Environment*            ev,
  771.                                       ODPasteAsResult&        pasteAsResult,
  772.                                       ODStorageUnit*        contentSU )
  773. {
  774.     SOM_Trace("Cappuccino","DoPaste");
  775.     
  776. #ifndef qViewerBuild
  777.     ASSERT_NOT_NULL(contentSU);
  778.     
  779.     CCappuccinoContent* content = new CCappuccinoContent(this);
  780.     TempRefCounted contentTemp = content;
  781.     
  782.     if ( pasteAsResult.translateKind != kODNULL )
  783.     {
  784.         content->InitByTranslating(ev, contentSU, pasteAsResult.translateKind,
  785.                                    pasteAsResult.selectedKind);
  786.     }
  787.     else
  788.     {
  789.         content->InitCappuccinoContent(ev, contentSU);
  790.     }
  791.     
  792.     // Create an action to paste the new content.
  793.     CPasteAction* action = new CPasteAction(this, content);
  794.     action->Perform(ev);
  795. #endif
  796. }
  797.  
  798.